﻿using System;
using System.Globalization;
using System.Linq;

using Telerik.Sitefinity;
using Telerik.Sitefinity.Abstractions;
using Telerik.Sitefinity.GenericContent.Model;
using Telerik.Sitefinity.Modules.Pages;
using Telerik.Sitefinity.Pages.Model;
using Telerik.Sitefinity.Security;
using Telerik.Sitefinity.Web;
using Telerik.Sitefinity.Fluent.Pages;

namespace Migration.Classes
{
	public static class MigrationPages
	{
		private static PageManager m_PageManager;
		private static RoleManager m_RoleManager;

		static MigrationPages()
		{
			m_PageManager = PageManager.GetManager();
			m_RoleManager = RoleManager.GetManager(MigrationSettings.RolesProvider);
		}

		private static void CheckManagers()
		{
			if (m_PageManager.Provider == null || MigrationSettings.ApplicationRestarted)
			{
				m_PageManager = PageManager.GetManager();
			}

			if (m_RoleManager.Provider == null || MigrationSettings.ApplicationRestarted)
			{
				m_RoleManager = RoleManager.GetManager(MigrationSettings.RolesProvider);
			}
		}

		public static void ImportPage(Telerik.Sitefinity.Services.Migration.MigrationPageGroup pageGroupContent)
		{
			CheckManagers();

			var isMultiLanguage = pageGroupContent.Pages.Count > 1;
			var pageLanguageLink = new PageLanguageLink();

			for (int i = 0; i < pageGroupContent.Pages.Count; i++)
			{
				var pageContent = pageGroupContent.Pages[i];
				var isFirstLanguage = i == 0;

				Guid id = pageContent.Id;
				string name = pageContent.MenuName;

				// Check if the page already exists
				int langId = pageContent.LangID;
				// If invariant culture set to default language
				if (langId == 127)
					langId = MigrationCultures.DefaultCulture.LCID;

				var cultureInfo = new CultureInfo(langId);

				// Save the current culture and temporary set the new one
				var currentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
				System.Threading.Thread.CurrentThread.CurrentUICulture = cultureInfo;

				PageNode checkItem = m_PageManager.GetPageNodes().Where(t => t.Id == id).FirstOrDefault();
				if (checkItem != null && isFirstLanguage)
				{
					MigrationSettings.PageNameMappings[pageContent.DefaultUrl] = MigrationUtils.GetFullPagePath(checkItem);

					var pageDataId = checkItem.Id;
					var checkPageData = m_PageManager.GetPageDataList().Where(t => t.Id == pageDataId).FirstOrDefault();
					if (checkPageData != null)
					{
						MigrationSettings.CreatedPages.Add(checkPageData);
					}

					MigrationLogger.AppendLogMessage(MigrationUtils.GetLocalizableSkipMessage(checkItem.Title, "") + "<br/>");
					return;
				}

				var urlName = MigrationUtils.GetUrlName(pageContent.Name);
				if (isMultiLanguage)
					urlName = urlName + "-" + cultureInfo.Name;

				// Check if there is already a page with this UrlName
                var checkUrlNameItem = m_PageManager.GetPageNodes().Where(t => t.UrlName == urlName).FirstOrDefault();
				if (checkUrlNameItem != null)
				{
					// Use the page Id since it's unique
					urlName = pageContent.Id.ToString();
				}

				Guid parentGuid = pageContent.ParentId;
				if (parentGuid == Guid.Empty)
				{
					parentGuid = SiteInitializer.FrontendRootNodeId;
				}

				PageNode parent;

				parent = m_PageManager.GetPageNode(parentGuid);
				
				PageData pageData = null;

				if (pageContent.PageType == "Group")
				{
					if (isMultiLanguage)
						MigrationLogger.AppendLogMessage(String.Format("Importing group page \"<b>{0}</b>\", language <b>{1}</b>.", name, cultureInfo.Name));
					else
						MigrationLogger.AppendLogMessage(String.Format("Importing group page \"<b>{0}</b>\".", name));
					MigrationLogger.AppendNewLine();

					if (!isFirstLanguage)
						id = Guid.NewGuid();

					using (var fluent = App.WorkWith())
					{
						var pageFacade = fluent.Page().CreateNewPageGroup(id).Done();
						pageFacade.MakeChildOf(parent.Id).SaveChanges();

						pageFacade.Do(p =>
						{
							p.DateCreated = pageContent.DateCreated;
							p.LastModified = pageContent.DateModified;
							p.Owner = MigrationUsers.GetUserByUsername(pageContent.Owner);
							p.Ordinal = pageContent.Ordinal;
							p.ShowInNavigation = pageContent.Navigable;

							if (isMultiLanguage)
							{
								p.Description[cultureInfo] = pageContent.Description;
								p.Title[cultureInfo] = name;
								p.UrlName[cultureInfo] = urlName;
							}
							else
							{
								p.Description = pageContent.Description;
								p.Title = name;
								p.UrlName = urlName;
							}
						});
					}
				}
				else if (pageContent.PageType == "Normal")
				{
					if (isMultiLanguage)
						MigrationLogger.AppendLogMessage(String.Format("Importing normal page \"<b>{0}</b>\", language <b>{1}</b>.", name, cultureInfo.Name));
					else
						MigrationLogger.AppendLogMessage(String.Format("Importing normal page \"<b>{0}</b>\".", name));
					MigrationLogger.AppendNewLine();

					if (!isFirstLanguage)
						id = Guid.NewGuid();

					pageData = m_PageManager.CreatePageData(id);

					if (isMultiLanguage)
					{
						pageData.Culture = cultureInfo.Name;
						pageData.UiCulture = cultureInfo.Name;
						pageData.LocalizationStrategy = Telerik.Sitefinity.Localization.LocalizationStrategy.Split;
						pageData.TranslationInitialized = true;

						pageLanguageLink.LanguageLinks.Add(pageData);
					}

					pageData.DateCreated = pageContent.DateCreated;
					pageData.LastModified = pageContent.DateModified;
					pageData.Owner = MigrationUsers.GetUserByUsername(pageContent.Owner);
					pageData.PublicationDate = pageData.DateCreated;
					pageData.Version = pageContent.Version;
					pageData.EnableViewState = !pageContent.DisableViewState;

					if (isMultiLanguage)
					{
						pageData.Keywords[cultureInfo] = pageContent.Keywords;
						pageData.Description[cultureInfo] = pageContent.Description;
						pageData.Title[cultureInfo] = name;
						pageData.HtmlTitle[cultureInfo] = pageContent.Title;
					}
					else
					{
						pageData.Keywords = pageContent.Keywords;
						pageData.Description = pageContent.Description;
						pageData.Title = name;
						pageData.HtmlTitle = pageContent.Title;
					}
					pageData.Theme = pageContent.Theme;
					if (pageContent.TemplateId != Guid.Empty)
					{
						Guid checkGuid = pageContent.TemplateId;
						PageTemplate template = m_PageManager.GetTemplates().Where(t => t.Id == checkGuid).FirstOrDefault();
						if (template != null)
						{
							pageData.Template = template;
						}
					}
					pageData.Status = ContentLifecycleStatus.Live;
					pageData.UIStatus = ContentUIStatus.Published;
					pageData.Visible = true;

					MigrationSettings.CreatedPages.Add(pageData);

					PageNode pageNode = m_PageManager.CreatePageNode(id);

					try
					{
						m_PageManager.ChangeParent(pageNode, parent);
					}
					catch (Exception)
					{
						return;
					}

					pageNode.DateCreated = pageData.DateCreated;
					pageNode.LastModified = pageData.LastModified;
					pageNode.Ordinal = pageContent.Ordinal;
					pageNode.Owner = MigrationUsers.GetUserByUsername(pageContent.Owner);
					pageNode.ShowInNavigation = pageContent.Navigable;
					if (isMultiLanguage)
					{
						pageNode.UrlName[cultureInfo] = urlName;
						pageNode.Description[cultureInfo] = pageData.Description;
						pageNode.Title[cultureInfo] = name;
					}
					else
					{
						pageNode.UrlName = urlName;
						pageNode.Description = pageData.Description;
						pageNode.Title = name;
					}

					pageNode.Page = pageData;

					// Add permissions to the page
					var permissions = m_PageManager.Provider.CreatePermission(SecurityConstants.Sets.Pages.SetName, pageNode.Id, SecurityManager.ApplicationRoles["Everyone"].Id);
					permissions.GrantActions(true, SecurityConstants.Sets.Pages.View);
					pageNode.Permissions.Add(permissions);

					// Parse the controls
					for (int j = 0; j < pageContent.Controls.Count; j++)
					{
						string result = MigrationControls.InsertControlToCollection<PageControl>(pageData.Controls, pageContent.Controls[j], false);
						MigrationLogger.AppendLogMessage(result);
					}
				}
				else // Page is external
				{
					if (isMultiLanguage)
						MigrationLogger.AppendLogMessage(String.Format("Importing external page \"<b>{0}</b>\", language <b>{1}</b>.", name, cultureInfo.Name));
					else
						MigrationLogger.AppendLogMessage(String.Format("Importing external page \"<b>{0}</b>\".", name));
					MigrationLogger.AppendNewLine();

					if (!isFirstLanguage)
						id = Guid.NewGuid();

					using (var fluent = App.WorkWith())
					{
						var pageFacade = fluent.Page().CreateNewPageGroup(id).Done();
						pageFacade.MakeChildOf(parent.Id);
						pageFacade.Do(n =>
						{
							n.Title = name;
							n.Description = pageContent.Description;
							n.NodeType = NodeType.OuterRedirect;
							n.LinkedNodeId = Guid.Empty;
							n.LinkedNodeProvider = String.Empty;
							n.Ordinal = pageContent.Ordinal;
							n.DateCreated = pageContent.DateCreated;
							n.LastModified = pageContent.DateModified;
							n.Owner = MigrationUsers.GetUserByUsername(pageContent.Owner);
							n.RedirectUrl = pageContent.ExternalUrl;
							n.OpenNewWindow = false;
							n.Page = null;
							n.ShowInNavigation = pageContent.Navigable;
							var lang = CultureInfo.InvariantCulture;
							pageFacade.PageManager.SetPageNodeUrlName(n, urlName, lang);
						});
					}
				}

				// Add the permissions
				/*
				foreach (var pagePermission in pageContent.Permissions)
				{
					string roleName = pagePermission.RoleName;
					var role = m_RoleManager.GetRoles().Where(r => r.Name == roleName).SingleOrDefault();
					if (role != null)
					{
						Permission permission = m_PageManager.CreatePermission(SecurityConstants.Sets.Pages.SetName, pageNode.Id, role.Id);
						permission.ApplicationName = pageNode.ApplicationName;
						permission.PrincipalId = role.Id;
						permission.Deny = pagePermission.Deny;
						permission.Grant = pagePermission.Grant;
						permission.SetName = name;
						permission.GrantActions(true, SecurityConstants.Sets.Pages.View);

						pageNode.Permissions.Add(permission);
					}
				}
				*/

				m_PageManager.SaveChanges();

				// Add permissions to the controls
				//if (pageContent.PageType == "Normal" && pageData != null)
				//{
				//	MigrationControls.AddPermissionForEveryone<PageControl>(pageData.Controls, m_PageManager);
				//}

				var justAddedPageNode = m_PageManager.GetPageNodes().Where(t => t.Id == id).FirstOrDefault();
				if (justAddedPageNode != null)
				{
					string sourceUrl1 = pageGroupContent.Pages[i].DefaultUrl.Replace("~/", String.Empty);
					string targetUrl1 = MigrationUtils.GetFullPagePath(justAddedPageNode).Replace("~/", String.Empty);

					MigrationSettings.PageNameMappings[sourceUrl1] = targetUrl1;
				}

				// Check if the page is the HomePage
                if (pageContent.IsHomePage)
                {
                    if (isMultiLanguage)
                    {
                        if (cultureInfo.Name == MigrationCultures.DefaultCulture.Name ||
                            cultureInfo.Name == String.Empty)
                        {
                            MigrationSettings.HomePageId = id;
                        }
                    }
                    else
                    {
                        MigrationSettings.HomePageId = pageContent.Id;
                    }
                }

				System.Threading.Thread.CurrentThread.CurrentUICulture = currentCulture;
			} // end for (int i = 0; i < pageGroupContent.Pages.Count; i++)

			if (isMultiLanguage)
			{
				foreach (var pageData in pageLanguageLink.LanguageLinks)
				{
					pageData.PageLanguageLink = pageLanguageLink;
				}
			}

			m_PageManager.SaveChanges();
			//SiteMapBase.Cache.Flush();
		}
	}
}
